package org.example.goods.facade.service;

import cn.hutool.core.lang.Assert;
import org.example.api.goods.constant.GoodsType;
import org.example.api.goods.request.GoodsFreezeInventoryRequest;
import org.example.api.goods.request.GoodsSaleRequest;
import org.example.api.goods.request.GoodsUnfreezeAndSaleRequest;
import org.example.api.goods.response.GoodsSaleResponse;
import org.example.api.goods.service.GoodsTransactionFacadeService;
import org.example.box.domain.service.BlindBoxService;
import org.example.collection.domain.service.CollectionService;
import org.example.lock.DistributeLock;
import org.example.rpc.facade.Facade;
import org.example.tcc.entity.TransConfirmSuccessType;
import org.example.tcc.entity.TransTrySuccessType;
import org.example.tcc.request.TccRequest;
import org.example.tcc.response.TransactionConfirmResponse;
import org.example.tcc.response.TransactionTryResponse;
import org.example.tcc.service.TransactionLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

public class GoodsTransactionFacadeServiceImpl implements GoodsTransactionFacadeService {

    private static final String ERROR_CODE_UNSUPPORTED_GOODS_TYPE = "UNSUPPORTED_GOODS_TYPE";

    @Autowired
    private CollectionService collectionService;

    @Autowired
    private BlindBoxService blindBoxService;

    @Autowired
    private TransactionLogService transactionLogService;
    @Override
    @Facade
    @Transactional(rollbackFor = Exception.class)
    @DistributeLock(keyExpression = "#request.bizNo",scene = "NORMAL_BUY_GOODS")
    public GoodsSaleResponse tryDecreaseInventory(GoodsSaleRequest request) {
        GoodsFreezeInventoryRequest goodsTrySaleRequest = new GoodsFreezeInventoryRequest(request.getIdentifier(),request.getGoodsId(),request.getQuantity());
        GoodsType goodsType = GoodsType.valueOf(request.getGoodsType());
        // 向tcc事务表中写入数据
        TransactionTryResponse transactionTryResponse = transactionLogService.tryTransaction(new TccRequest(request.getBizNo(), "normalBuy", goodsType.name()));
        Assert.isTrue(transactionTryResponse.getSuccess(),"transaction try failed");
        if(transactionTryResponse.getTransTrySuccessType() == TransTrySuccessType.TRY_SUCCESS){
            Boolean freezeResult = switch (goodsType){
                case COLLECTION -> collectionService.freezeInventory(goodsTrySaleRequest);
                default -> throw new UnsupportedOperationException(ERROR_CODE_UNSUPPORTED_GOODS_TYPE);
            };
            Assert.isTrue(freezeResult, "freeze inventory failed");
            GoodsSaleResponse response = new GoodsSaleResponse();
            response.setSuccess(true);
            return response;
        }
        return null;
    }

    @Override
    @Facade
    @Transactional(rollbackFor = Exception.class)
    @DistributeLock(keyExpression = "#request.bizNo",scene = "NORMAL_BUY_GOODS")
    public GoodsSaleResponse confirmDecreaseInventory(GoodsSaleRequest request) {
        GoodsUnfreezeAndSaleRequest unfreezeAndSaleRequest = new GoodsUnfreezeAndSaleRequest(request.getBizNo(), request.getGoodsId(), request.getQuantity());
        GoodsType goodsType = GoodsType.valueOf(request.getGoodsType());
        TransactionConfirmResponse transactionConfirmResponse = transactionLogService.confirmTransaction(new TccRequest(request.getBizNo(), "normalBuy", goodsType.name()));
        Assert.isTrue(transactionConfirmResponse.getSuccess(),"transaction confirm failed");
        if(transactionConfirmResponse.getTransConfirmSuccessType() == TransConfirmSuccessType.CONFIRM_SUCCESS){
            Boolean unfreezeResult = switch (goodsType) {
                case COLLECTION -> collectionService.unfreezeAndSale(unfreezeAndSaleRequest);
                default -> throw new UnsupportedOperationException(ERROR_CODE_UNSUPPORTED_GOODS_TYPE);
            };
            Assert.isTrue(unfreezeResult, "unfreeze inventory failed");

            GoodsSaleResponse response = new GoodsSaleResponse();
            response.setSuccess(true);
            return response;
        }

        return new GoodsSaleResponse.GoodsResponseBuilder().buildSuccess();
    }

    @Override
    public GoodsSaleResponse cancelDecreaseInventory(GoodsSaleRequest request) {
        return null;
    }
}
